package icasue.stronger.wareable.logicstronger.logicsupport;

import icasue.base.utils.wareable.CLog;
import icasue.stronger.wareable.logicstronger.StrongerAdvice;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2020/6/28 下午5:18
 * @UpdateDate:
 * @Description: 性能监控逻辑
 */
@Slf4j
public class TimeStrongerLogic extends StrongerAdvice<Integer,Long> {

    private BeforeMethodLogic timeBeforeMethodLogic = (proxyClass, invoker, method,params) -> {
        Map<Integer, Long> threadInvokeChain = processBuffer.get();
        if(threadInvokeChain == null) {
            threadInvokeChain = new HashMap<>();
            processBuffer.set(threadInvokeChain);
        }
        threadInvokeChain.put(method.hashCode(), System.currentTimeMillis());
        return null;
    };

    private AfterMethodLogic timeAfterMethodLogic = (result,proxyClass, invoker, method,params) -> {
        Map<Integer, Long> threadInvokeChain = processBuffer.get();
        if(threadInvokeChain == null){
            return null;
        }
        Long inTime = null;
        try { inTime = threadInvokeChain.remove(method.hashCode()); }catch (Exception e){ }finally {
            if(threadInvokeChain.size() == 0) {
                processBuffer.remove();
            }
        }
        long outTime = System.currentTimeMillis();
        if(inTime != null) {
            CLog.info("\t%s 方法耗时 %s millions." ,
                    method.getDeclaringClass().getCanonicalName() + " :: " + method.getName() ,
                    (outTime - inTime)
            );
        }
        return null;
    };

    /*
    private ExceptionMethodHandleLogic timeExceptionMethodHandleLogic = new ExceptionMethodHandleLogic() {
        @Override
        public Object handleMethodException(Throwable throwable, Object result, Class proxyClass,
                                            Object invoker, Method method, Object... params) throws Throwable {
            Map<Integer, Long> threadInvokeChain = processBuffer.get();
            if(threadInvokeChain == null){
                return null;
            }
            Long inTime = null;
            try { inTime = threadInvokeChain.remove(method.hashCode()); }catch (Exception e){ }finally {
                if(threadInvokeChain.size() == 0) {
                    processBuffer.remove();
                }
            }
            long outTime = System.currentTimeMillis();
            if(inTime != null) {
                CLog.info("\t%s 方法耗时 %s millions." ,
                        method.getDeclaringClass().getCanonicalName() + " :: " + method.getName() ,
                        (outTime - inTime)
                );
            }
            return null;
        }

        @Override
        public Class support() {
            return null;
        }
    };*/

    public TimeStrongerLogic(){
        super();
        addBeforeMethodLogic(timeBeforeMethodLogic);
        addAfterMethodLogic(timeAfterMethodLogic);
        //addExceptionMethodHandleLogic(timeExceptionMethodHandleLogic);
    }

}
